using Microsoft.EntityFrameworkCore;
using Order.Api.Read.Application.Command;
using Order.Api.Read.Dto.Order;
using Order.Api.Read.Service.DrugOrdersService;
using Order.ErrorCode;
using Order.Domain.OrderDomain;
using Order.Interstructrue;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Order.Api.Read.Service.DrugOrdersService
{
    /// <summary>
    /// 药品订单服务实现类
    /// </summary>
    public class DrugOrdersService : IDrugOrdersService
    {
        private readonly MedicalDbContext _context;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">数据库上下文</param>
        public DrugOrdersService(MedicalDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context), "数据库上下文不能为空");
        }

        /// <summary>
        /// 获取药品订单分页数据
        /// 支持关键字搜索、时间范围筛选、状态筛选
        /// 订单金额通过药品表中的单价*数量计算
        /// </summary>
        /// <param name="command">分页查询命令</param>
        /// <returns>分页结果</returns>
        /// <exception cref="ArgumentNullException">当command为null时抛出</exception>
        public async Task<ApiPageIng<DrugOrdersPageDto>> GetDrugOrdersPageAsync(DrugOrdersPageCommand command)
        {
            try
            {
                // 参数验证
                if (command == null)
                {
                    throw new ArgumentNullException(nameof(command), "查询命令不能为空");
                }

                // 验证查询条件
                if (command.Query == null)
                {
                    command.Query = new DrugOrdersQueryDto();
                }

                // 验证分页参数
                if (command.Query.PageIndex <= 0)
                {
                    command.Query.PageIndex = 1;
                }

                if (command.Query.PageSize <= 0)
                {
                    command.Query.PageSize = 10;
                }

                // 构建基础查询，关联患者表和药品表
                var query = from drugOrder in _context.DrugOrders
                            join patient in _context.Patient on drugOrder.PatientId equals patient.Id into patientJoin
                            from patient in patientJoin.DefaultIfEmpty()
                            join drug in _context.Drug on drugOrder.Id equals drug.DrugOrderId into drugJoin
                            from drug in drugJoin.DefaultIfEmpty()
                            where !drugOrder.IsDeleted
                            group new { drugOrder, patient, drug } by new
                            {
                                drugOrder.Id,
                                drugOrder.OrderNo,
                                drugOrder.CreateTime,
                                drugOrder.OrderStatus,
                                drugOrder.PatientId,
                                patient.Phone,
                                patient.PatientName
                            } into grouped
                            select new DrugOrdersPageDto
                            {
                                Id = grouped.Key.Id,
                                OrderNo = grouped.Key.OrderNo,
                                CreateTime = grouped.Key.CreateTime,
                                Phone = grouped.Key.Phone,
                                Consignee = grouped.Key.PatientName,
                                OrderAmount = grouped.Sum(x => (x.drug.UnitPrice ?? 0) * (x.drug.Num ?? 0)),
                                OrderStatus = grouped.Key.OrderStatus,
                                PatientId = grouped.Key.PatientId
                            };

                // 应用关键字查询条件
                if (!string.IsNullOrEmpty(command.Query.Keyword))
                {
                    var keyword = command.Query.Keyword.Trim();
                    query = query.Where(x =>
                        (x.OrderNo != null && x.OrderNo.Contains(keyword)) ||
                        (x.Consignee != null && x.Consignee.Contains(keyword)) ||
                        (x.Phone != null && x.Phone.Contains(keyword))
                    );
                }

                // 应用时间范围筛选
                if (command.Query.StartTime.HasValue)
                {
                    query = query.Where(x => x.CreateTime >= command.Query.StartTime.Value);
                }

                if (command.Query.EndTime.HasValue)
                {
                    query = query.Where(x => x.CreateTime <= command.Query.EndTime.Value);
                }

                // 应用状态筛选
                if (command.Query.OrderStatus.HasValue)
                {
                    query = query.Where(x => x.OrderStatus == command.Query.OrderStatus.Value);
                }

                // 获取总数
                var totalCount = await query.CountAsync();

                // 分页查询
                var pageData = await query
                    .OrderByDescending(x => x.CreateTime) // 按创建时间倒序排列
                    .Skip((command.Query.PageIndex - 1) * command.Query.PageSize)
                    .Take(command.Query.PageSize)
                    .ToListAsync();

                // 设置枚举名称
                foreach (var item in pageData)
                {
                    item.OrderStatusName = GetEnumName(item.OrderStatus);
                }

                // 返回分页结果
                return new ApiPageIng<DrugOrdersPageDto>
                {
                    Data = pageData,
                    TotalCount = totalCount,
                    PageIndex = command.Query.PageIndex,
                    PageSize = command.Query.PageSize
                };
            }
            catch (Exception ex)
            {
                // 记录异常日志
                // TODO: 添加日志记录
                throw new Exception($"获取药品订单分页数据时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取药品订单详情
        /// 包含订单基本信息、收货人信息、货物信息列表
        /// </summary>
        /// <param name="command">详情查询命令</param>
        /// <returns>订单详情</returns>
        /// <exception cref="ArgumentNullException">当command为null时抛出</exception>
        public async Task<DrugOrdersDetailDto> GetDrugOrdersDetailAsync(DrugOrdersDetailCommand command)
        {
            try
            {
                // 参数验证
                if (command == null)
                {
                    throw new ArgumentNullException(nameof(command), "详情查询命令不能为空");
                }

                if (command.Id <= 0)
                {
                    throw new ArgumentException("订单ID必须大于0", nameof(command.Id));
                }

                // 查询药品订单基本信息
                var drugOrder = await _context.DrugOrders
                    .FirstOrDefaultAsync(x => x.Id == command.Id && !x.IsDeleted);

                if (drugOrder == null)
                {
                    throw new InvalidOperationException($"未找到ID为{command.Id}的药品订单");
                }

                // 查询患者信息（收货人信息）
                var patient = await _context.Patient
                    .FirstOrDefaultAsync(x => x.Id == drugOrder.PatientId && !x.IsDeleted);

                // 查询药品信息列表
                var drugs = await _context.Drug
                    .Where(x => x.DrugOrderId == command.Id && !x.IsDeleted)
                    .ToListAsync();

                // 构建详情DTO
                var detailDto = new DrugOrdersDetailDto
                {
                    Id = drugOrder.Id,
                    OrderNo = drugOrder.OrderNo,
                    OrderAmount = drugs.Sum(x => (x.UnitPrice ?? 0) * (x.Num ?? 0)),
                    OrderStatus = drugOrder.OrderStatus,
                    OrderStatusName = GetEnumName(drugOrder.OrderStatus),
                    CreateTime = drugOrder.CreateTime,
                    ConsigneeInfo = patient != null ? new ConsigneeInfoDto
                    {
                        Consignee = patient.PatientName,
                        Phone = patient.Phone,
                        Address = patient.Address
                    } : null,
                    GoodsInfoList = drugs.Select(x => new GoodsInfoDto
                    {
                        DrugName = x.DrugName,
                        Num = x.Num,
                        Specif = x.Specif,
                        Dosage = x.Dosage,
                        UnitPrice = x.UnitPrice,
                        SubTotal = (x.UnitPrice ?? 0) * (x.Num ?? 0)
                    }).ToList()
                };

                return detailDto;
            }
            catch (Exception ex)
            {
                // 记录异常日志
                // TODO: 添加日志记录
                throw new Exception($"获取药品订单详情时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取枚举名称
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="enumValue">枚举值</param>
        /// <returns>枚举名称</returns>
        private string? GetEnumName<T>(T? enumValue) where T : struct, Enum
        {
            try
            {
                if (!enumValue.HasValue)
                    return null;

                return enumValue.Value.ToString();
            }
            catch (Exception ex)
            {
                // 记录异常日志
                // TODO: 添加日志记录
                return enumValue?.ToString();
            }
        }
    }
}